package com.jichaoyun.sys.service.impl;

import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jichaoyun.model.entity.DcAlarm;
import com.jichaoyun.model.entity.LineInfo;
import com.jichaoyun.model.entity.StationInfo;

import com.jichaoyun.model.entity.User;
import com.jichaoyun.common.enums.MyExceptiontType;
import com.jichaoyun.common.ex.MyException;
import com.jichaoyun.sys.mapper.DcAlarmMapper;
import com.jichaoyun.sys.mapper.LineInfoMapper;
import com.jichaoyun.sys.mapper.StationInfoMapper;
import com.jichaoyun.sys.mapper.UserMapper;
import com.jichaoyun.model.vo.AlarmVo;

import com.jichaoyun.sys.service.DcAlarmService;
import com.jichaoyun.common.utils.PoiExcelStyle;
import com.jichaoyun.sys.service.IStationInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
* @author ljc
* @description 针对表【dcAlarm】的数据库操作Service实现
* @createDate 2023-11-29 14:35:11
*/
@Service
public class DcAlarmServiceImpl extends ServiceImpl<DcAlarmMapper, DcAlarm>
    implements DcAlarmService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private LineInfoMapper lineInfoMapper;

    @Autowired
    private DcAlarmMapper dcAlarmMapper;

    @Autowired
    private IStationInfoService stationInfoService;

    @Autowired
    private StationInfoMapper stationInfoMapper;
    /**
     * 直流报警信息已读接口
     * @param userId
     */
    @Override
    public void MakeAlarmRead(Integer id,Integer userId) {
        LambdaQueryWrapper<User> queryWrapper0 = new LambdaQueryWrapper<>();
        queryWrapper0.eq(User::getId,userId);
        User user = this.userMapper.selectOne(queryWrapper0);

        if(user.getUserRole() != 0){

            LambdaQueryWrapper<DcAlarm> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(DcAlarm::getId,id);
            DcAlarm dcAlarm = this.dcAlarmMapper.selectOne(wrapper);
            dcAlarm.setIsReadAdmin(true);
            this.dcAlarmMapper.updateById(dcAlarm);
        }else {

            LambdaQueryWrapper<DcAlarm> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(DcAlarm::getId,id);
            DcAlarm dcAlarm = this.dcAlarmMapper.selectOne(wrapper);
            dcAlarm.setIsRead(true);
            this.dcAlarmMapper.updateById(dcAlarm);
        }


    }
    /**
     * 全部直流报警信息已读接口
     * @param userId
     */
    @Override
    public void MakeAlarmRead(Integer userId) {

        LambdaQueryWrapper<User> queryWrapper0 = new LambdaQueryWrapper<>();
        queryWrapper0.eq(User::getId,userId);
        User user = this.userMapper.selectOne(queryWrapper0);

        if(user.getUserRole() != 0){
            LambdaQueryWrapper<DcAlarm> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(DcAlarm::getIsReadAdmin,0);
            List<DcAlarm> dcAlarmList = this.dcAlarmMapper.selectList(lambdaQueryWrapper);

            for(DcAlarm dcAlarm:dcAlarmList){
                dcAlarm.setIsReadAdmin(true);
                this.dcAlarmMapper.updateById(dcAlarm);
            }

        }
        else {
            LambdaQueryWrapper<StationInfo> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(StationInfo::getUserId,userId);
            List<StationInfo> stationInfoList = this.stationInfoMapper.selectList(queryWrapper);

            List<Integer> stationNoList = new ArrayList<>();
            for(StationInfo stationInfo:stationInfoList){
                stationNoList.add(stationInfo.getStationNo());
            }
            if(stationNoList.isEmpty()){
                throw new MyException(MyExceptiontType.Other,null);
            }

            LambdaQueryWrapper<DcAlarm> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.in(DcAlarm::getStation,stationNoList)
                        .eq(DcAlarm::getIsRead,0);
            List<DcAlarm> dcAlarmList = this.dcAlarmMapper.selectList(lambdaQueryWrapper);
            for(DcAlarm dcAlarm:dcAlarmList){
                dcAlarm.setIsRead(true);
                this.dcAlarmMapper.updateById(dcAlarm);
            }
        }

    }
    /**
     * 查询未读的直流报警信息
     * @return
     */
    @Override
    public List<Map<String, Object>> pollingDb(Integer userId) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getId,userId);
        User user = this.userMapper.selectOne(queryWrapper);
        if(user.getUserRole() != 0) {
            //查询所有未读的报警
            LambdaQueryWrapper<DcAlarm> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(DcAlarm::getIsReadAdmin, 0).orderByAsc(DcAlarm::getId);
            List<DcAlarm> list = dcAlarmMapper.selectList(wrapper);

            if (list != null) {
                List<Map<String, Object>> resList = new ArrayList<>();

                Map<Integer, String> map1 = new HashMap<>();
                Map<Integer,Integer> map2 = new HashMap<>();
                for (DcAlarm item : list) {
                    //一个站点的通讯报警只取最新的一条
                    map1.put(item.getStation(), item.getStartTime().toString());
                    map2.put(item.getStation(),item.getId());
                }
                for (Integer item : map1.keySet()) {
                    Map<String, Object> map = new HashMap<>();

                    map.put("报警类型", "直流报警");
                    map.put("报警站点", stationInfoService.getById(item).getStationName());
                    map.put("报警时间", map1.get(item));
                    map.put("id",map2.get(item));
                    resList.add(map);
                }
                return resList;
            }
        }else {
            LambdaQueryWrapper<StationInfo> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.eq(StationInfo::getUserId,userId);
            List<StationInfo> stationInfoList = this.stationInfoMapper.selectList(queryWrapper1);

            List<Integer> stationNoList = new ArrayList<>();
            for(StationInfo stationInfo:stationInfoList){
                stationNoList.add(stationInfo.getStationNo());
            }
            //查询所有未读的报警
            LambdaQueryWrapper<DcAlarm> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(DcAlarm::getIsRead, 0)
                    .in(DcAlarm::getStation,stationNoList)
                    .orderByAsc(DcAlarm::getId);
            List<DcAlarm> list = dcAlarmMapper.selectList(wrapper);

            if (list != null) {
                List<Map<String, Object>> resList = new ArrayList<>();

                Map<Integer, String> map1 = new HashMap<>();
                Map<Integer,Integer> map2 = new HashMap<>();
                for (DcAlarm item : list) {
                    //一个站点的通讯报警只取最新的一条
                    map1.put(item.getStation(), item.getStartTime().toString());
                    map2.put(item.getStation(),item.getId());
                }
                for (Integer item : map1.keySet()) {
                    Map<String, Object> map = new HashMap<>();

                    map.put("id",map2.get(item));
                    map.put("报警类型", "直流报警");
                    map.put("报警站点", stationInfoService.getById(item).getStationName());
                    map.put("报警时间", map1.get(item));
                    resList.add(map);
                }
                return resList;
            }
        }
        return null;
    }

    @Override
    public Map<String, Long> eachAlarmProportion() {
        Map<String,Long> map = new HashMap<>();
        LambdaQueryWrapper<DcAlarm> lambdaQueryWrapper_dc = new LambdaQueryWrapper<>();
        lambdaQueryWrapper_dc.ge(DcAlarm::getId,0);
        long dc_cnt = this.baseMapper.selectCount(lambdaQueryWrapper_dc);
        map.put("直流报警",dc_cnt);
        return map;
    }

    /**
     * 获取线路直流报警信息
     * @param line_name
     * @param date
     * @param pageNo
     * @return
     */
    @Override
    public IPage<List<AlarmVo>> getDcAlarmAlarm(String line_name, String date, Integer pageNo) {
        QueryWrapper<LineInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("line_alias",line_name).or().eq("line_name",line_name);

        Integer line_id = this.lineInfoMapper.selectOne(wrapper).getLineNum();

        IPage<List<AlarmVo>> resultIPage = new Page<>(pageNo,20);

        return this.dcAlarmMapper.selectDcAlarmPage(resultIPage,date,getNextDay(date),line_id);
    }

    private String getNextDay(String dateTime) {
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd");
        Date datetime = null;
        try{
            datetime = simpleDateFormat.parse(dateTime);
        }catch (ParseException e){
            log.error("String转Date日期失败:",e);
        }
        Calendar calendar=Calendar.getInstance();
        calendar.setTime(datetime);
        //往后一天
        calendar.add(Calendar.DAY_OF_MONTH,1);
        return simpleDateFormat.format(calendar.getTime());
    }
    /**
     * 获取站点直流报警信息
     * @param station
     * @param date
     * @return
     */
    @Override
    public Map<String, List<DcAlarm>> getDcAlarmInfo(Integer station, String date) {
        Map<String,List<DcAlarm>> result = new HashMap<>();

        LambdaQueryWrapper<DcAlarm> wrapper = new LambdaQueryWrapper<>();
        wrapper.ge(DcAlarm::getStartTime,date).lt(DcAlarm::getStartTime,getNextDay(date));
        List<DcAlarm> listPower = this.dcAlarmMapper.selectList(wrapper);

        for(DcAlarm item : listPower){
            if(item.getEndTime() == null){
                item.setEndTime(LocalDateTime.now());
                item.setBetweenMin((int) Duration.between(item.getStartTime(),LocalDateTime.now()).toMinutes());
            }
            if(item.getStation().equals(station)){
                String key = stationInfoService.getById(item.getStation()).getStationName();
                if(result.containsKey(key)){
                    result.get(key).add(item);
                }else {
                    result.put(key,new ArrayList<>());
                    result.get(key).add(item);
                }
            }


        }
        return result;
    }

    @Override
    public List<Map<String, Object>> getAllDcAlarm(String line_name, String date) {
        List<Map<String,Object>> resList = new ArrayList<>();

        QueryWrapper<LineInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("line_alias",line_name).or().eq("line_name",line_name);

        Integer line_id = this.lineInfoMapper.selectOne(wrapper).getLineNum();

        LambdaQueryWrapper<StationInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StationInfo::getLineId,line_id);
        List<StationInfo> stationInfoList = this.stationInfoMapper.selectList(queryWrapper);

        List<Integer> stationNoList = new ArrayList<>();
        for(StationInfo stationInfo:stationInfoList){
            stationNoList.add(stationInfo.getStationNo());
        }

        LambdaQueryWrapper<DcAlarm> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(DcAlarm::getStation,stationNoList)
                .ge(DcAlarm::getStartTime,date)
                .lt(DcAlarm::getStartTime,getNextDay(date))
                .orderByAsc(DcAlarm::getStation);
        List<DcAlarm> dcAlarmList = this.dcAlarmMapper.selectList(lambdaQueryWrapper);

        for(DcAlarm dcAlarm:dcAlarmList){
            Map<String,Object> map = new LinkedHashMap<>();

            map.put("站点编号",dcAlarm.getStation());
            map.put("站点名称",stationInfoService.getById(dcAlarm.getStation()).getStationName());
            map.put("报警开始时间",dcAlarm.getStartTime());
            map.put("报警结束时间",dcAlarm.getEndTime());
            map.put("报警时长",dcAlarm.getBetweenMin());

            resList.add(map);
        }
        return resList;
    }
    /**
     * 将站点直流报警信息导出到excel
     * @param line_name
     * @param date
     * @param response
     * @throws IOException
     */
    @Override
    public void getAlarmExcel(String line_name, String date, HttpServletResponse response) throws IOException {
        List<Map<String,Object>> resList = getAllDcAlarm(line_name,date);

        // 创建一个 ExcelWriter 把 list 数据用这个writer写出来(生成出来)
        ExcelWriter wr = ExcelUtil.getWriter( true);
        wr.write(resList, true);

        //设置excel的导出样式
        PoiExcelStyle.setStyleSet(wr,resList);

        // 定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        // 将字符串转换为 LocalDate
        LocalDate theDate = LocalDate.parse(date, formatter);

        // 创建 DateTimeFormatter 对象，定义日期格式
        DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy年M月d日 ");
        // 使用 DateTimeFormatter 格式化 LocalDateTime 对象
        String formattedDate = theDate.format(formatter1);

        // 把这个 excel 下载下来
        response.setContentType("application/vnd.gpenxmlfonmats-officedocument.spreadsheetml.sheet;charset=utf-8");
        String fileName = URLEncoder.encode(formattedDate + line_name +"直流报警表", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader( "Content-Disposition", "attachment;filename="+fileName+".xlsx");
        ServletOutputStream out = response.getOutputStream();
        wr.flush(out,true);
        wr.close();
        IoUtil.close(System.out);
    }
}




